﻿using System.Collections.Generic;
using System.Linq;
using Missbot.Common;
using Missbot.Service;
using Dolany.UtilityTool;
using Missbot.AIModule.OnlineStore;

namespace Missbot.AIModule.Pet.Cooking
{
    public class CookingRecord : DbBaseEntity
    {
        public string UserID { get; set; }

        public List<string> LearndDietMenu { get; set; } = new();

        public Dictionary<string, int> CookedDietDic { get; set; } = new();

        public Dictionary<string, int> FlavoringDic { get; set; } = new();

        public Dictionary<string, int> CookingHistory { get; set; } = new();
    }

    public static class CookingRecordDA
    {
        private static HonorSvc HonorSvc => AutofacSvc.Resolve<HonorSvc>();
        private static CookingDietSvc CookingDietSvc => AutofacSvc.Resolve<CookingDietSvc>();

        public static int TotalPrice(this CookingRecord entity)
        {
            var itemConsumeDic = entity.ItemConsumeDic();
            var flavoringTotal = entity.FlavoringTotal();

            return itemConsumeDic.Sum(p => HonorSvc.FindItem(p.Key).Price * p.Value) + flavoringTotal * 20;
        }

        public static int FlavoringTotal(this CookingRecord entity)
        {
            var flavoringTotal = 0;
            foreach (var (key, value) in entity.CookingHistory)
            {
                var diet = CookingDietSvc[key];
                flavoringTotal += diet?.Flavorings?.Sum(p => p.Value) * value ?? 0;
            }

            return flavoringTotal;
        }

        public static Dictionary<string, int> ItemConsumeDic(this CookingRecord entity)
        {
            var itemConsumeDic = new Dictionary<string, int>();
            foreach (var (key, value) in entity.CookingHistory)
            {
                var diet = CookingDietSvc[key];
                if (diet.Materials.IsNullOrEmpty())
                {
                    continue;
                }

                foreach (var (material, count) in diet.Materials)
                {
                    if (!itemConsumeDic.ContainsKey(material))
                    {
                        itemConsumeDic.Add(material, 0);
                    }

                    itemConsumeDic[material] += count * value;
                }
            }

            return itemConsumeDic;
        }

        public static CookingRecord Get(string UserID)
        {
            var record = MongoService<CookingRecord>.GetOnly(p => p.UserID == UserID);
            if (record != null)
            {
                return record;
            }

            record = new CookingRecord { UserID = UserID };
            MongoService<CookingRecord>.Insert(record);

            return record;
        }

        public static void AddDiet(this CookingRecord entity, string name, int count = 1)
        {
            if (!entity.CookedDietDic.ContainsKey(name))
            {
                entity.CookedDietDic.Add(name, 0);
            }

            entity.CookedDietDic[name] += count;
            entity.CookingHistory ??= new Dictionary<string, int>();

            if (!entity.CookingHistory.ContainsKey(name))
            {
                entity.CookingHistory.Add(name, 0);
            }

            entity.CookingHistory[name] += count;
        }

        public static void DietConsume(this CookingRecord entity, string name, int count = 1)
        {
            if (entity.CookedDietDic.ContainsKey(name))
            {
                entity.CookedDietDic[name] -= count;
            }
        }

        public static bool CheckDiet(this CookingRecord entity, string name, int count = 1)
        {
            return entity.CookedDietDic.ContainsKey(name) && entity.CookedDietDic[name] >= count;
        }

        public static bool CheckFlavorings(this CookingRecord entity, Dictionary<string, int> fDic)
        {
            if (entity.FlavoringDic.IsNullOrEmpty())
            {
                return false;
            }

            foreach (var (name, count) in fDic)
            {
                if (!entity.FlavoringDic.ContainsKey(name) || entity.FlavoringDic[name] < count)
                {
                    return false;
                }
            }

            return true;
        }

        public static void FlavoringConsume(this CookingRecord entity, Dictionary<string, int> fDic)
        {
            if (fDic.IsNullOrEmpty())
            {
                return;
            }

            foreach (var (name, count) in fDic)
            {
                entity.FlavoringDic[name] -= count;
            }
        }

        public static void FlavoringIncome(this CookingRecord entity, string flavoringName, int count = 1)
        {
            if (!entity.FlavoringDic.ContainsKey(flavoringName))
            {
                entity.FlavoringDic.Add(flavoringName, 0);
            }

            entity.FlavoringDic[flavoringName] += count;
        }

        public static void FlavoringIncome(this CookingRecord entity, Dictionary<string, int> flavoringDic)
        {
            foreach (var (name, count) in flavoringDic)
            {
                entity.FlavoringIncome(name, count);
            }
        }

        public static void Update(this CookingRecord entity)
        {
            entity.CookedDietDic.Remove(p => p == 0);
            entity.FlavoringDic.Remove(p => p == 0);

            MongoService<CookingRecord>.Update(entity);
        }
    }
}